#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstring>
#include <filesystem>
#include <stdexcept>

namespace fs = std::filesystem;

// 定义帧结构
struct Frame {
    unsigned char startDelimiter; // 帧首定界符
    unsigned char destAddr;       // 目的地址
    unsigned char srcAddr;        // 源地址
    unsigned short length;        // 长度
    std::vector<unsigned char> payload; // 载荷
    unsigned int crc;             // CRC校验
};

// CRC校验函数（简化版）
unsigned int calculateCRC(const std::vector<unsigned char>& payload) {
    unsigned int crc = 0xFFFFFFFF;
    for (auto byte : payload) {
        crc ^= byte;
        for (int i = 0; i < 8; i++) {
            if (crc & 1) {
                crc = (crc >> 1) ^ 0x82F63B78;
            } else {
                crc >>= 1;
            }
        }
    }
    return ~crc;
}

// 转义帧中的定界符
void escapeDelimiter(std::vector<unsigned char>& data, unsigned char delimiter) {
    for (size_t i = 0; i < data.size(); ++i) {
        if (data[i] == delimiter) {
            data[i] = 0xCC;
            if (i + 1 < data.size()) {
                data[i + 1] = 0xCA;
                ++i; // 跳过转义字符
            }
        }
    }
}

// 编码器逻辑
void encode(const std::string& inputDir, int mtu, const std::string& outputFile, int maxLength) {
    // 读取输入目录下的所有.bin文件
    std::vector<Frame> frames;
    for (const auto& entry : fs::directory_iterator(inputDir)) {
        if (entry.path().extension() == ".bin") {
            std::ifstream file(entry.path(), std::ios::binary);
            std::vector<unsigned char> data((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
            escapeDelimiter(data, 0xCA);
            Frame frame;
            frame.startDelimiter = 0xCA;
            frame.destAddr = 1; // 示例目的地址
            frame.srcAddr = 2;  // 示例源地址
            frame.length = data.size();
            frame.payload = data;
            frame.crc = calculateCRC(data);
            frames.push_back(frame);
        }
    }

    // 将帧写入输出文件
    std::ofstream outFile(outputFile, std::ios::binary);
    for (const auto& frame : frames) {
        outFile.write(reinterpret_cast<const char*>(&frame.startDelimiter), 1);
        outFile.write(reinterpret_cast<const char*>(&frame.destAddr), 1);
        outFile.write(reinterpret_cast<const char*>(&frame.srcAddr), 1);
        outFile.write(reinterpret_cast<const char*>(&frame.length), 2);
        outFile.write(reinterpret_cast<const char*>(frame.payload.data()), frame.payload.size());
        unsigned int crc = calculateCRC(frame.payload);
        outFile.write(reinterpret_cast<const char*>(&crc), 4);
    }
}

// 解码器逻辑
void decode(const std::string& inputFile, const std::string& outputDir) {
    // 读取输入文件
    std::ifstream inFile(inputFile, std::ios::binary);
    std::vector<unsigned char> data((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());

    // 解码帧
    size_t pos = 0;
    while (pos < data.size()) {
        Frame frame;
        frame.startDelimiter = data[pos++];
        frame.destAddr = data[pos++];
        frame.srcAddr = data[pos++];
        frame.length = *reinterpret_cast<unsigned short*>(&data[pos]);
        pos += 2;
        frame.payload.assign(data.begin() + pos, data.begin() + pos + frame.length);
        pos += frame.length;
        frame.crc = *reinterpret_cast<unsigned int*>(&data[pos]);
        pos += 4;

        // 转义回定界符
        for (size_t i = 0; i < frame.payload.size(); ++i) {
            if (frame.payload[i] == 0xCC && frame.payload[i + 1] == 0xCA) {
                frame.payload[i] = 0xCA;
                frame.payload.erase(frame.payload.begin() + i + 1);
            }
        }

        // 将帧写入输出文件
        std::string filename = std::to_string(frame.destAddr) + ".bin";
        std::ofstream outFile(outputDir + "/" + filename, std::ios::binary);
        outFile.write(reinterpret_cast<const char*>(frame.payload.data()), frame.payload.size());
    }
}

int main(int argc, char* argv[]) {
    if (argc < 5) {
        std::cerr << "Usage: " << argv[0] << " <encode/decode> <inputDir/inputFile> <mtu/--> <outputFile/--> <maxLength/-->" << std::endl;
        return 1;
    }

    std::string command = argv[1];
    if (command == "encode") {
        encode(argv[2], std::stoi(argv[3]), argv[4], std::stoi(argv[5]));
    } else if (command == "decode") {
        decode(argv[2], argv[3]);
    } else {
        std::cerr << "Invalid command: " << command << std::endl;
        return 1;
    }

    return 0;
}